Shader "Level4/RTM/ReliefMapping" {
	Properties {
		_colorMap("Base (RGB)", 2d) = "white" {}
		_reliefMap("reliefMap",2d) = "white"{}
		
		shine("shine",float) = 32
		tile("tile",float) = 1
		depth("depth",float) = 0.1
		
		ambientColor("ambientColor",color) = (.2,.2,.2)
		diffuseColor("diffuseColor",color) = (.2,.2,.2)
		specularColor("specularColor",color) = (.2,.2,.2)
		
		lightPos("pointLight",Vector) = (-10,0,-10)
	}
	
	CGINCLUDE
		#include "Level4.cginc"
		#define DEPTH_BIAS
		#define BORDER_CLAMP
		
	
		float shine;
		float tile;
		float depth;
		float depth_bias;
		float border_clamp;
		
		sampler2D _colorMap;
		sampler2D _reliefMap;
		float3 lightPos;
		
		float3 ambientColor;
		float3 diffuseColor;
		float3 specularColor;
		
		struct a2v{
			float4 vertex : POSITION;
			float4 tangent : TANGENT;
			float3 normal : NORMAL;
			float2 texcoord : TEXCOORD0;
		};
		struct v2f{
			float4 hpos : POSITION;
			float3 eye : TEXCOORD0;
			float3 light : TEXCOORD1;
			float2 texcoord : TEXCOORD2;
		};
		
		v2f vert(a2v IN){
			v2f OUT;
			float4 pos = float4(IN.vertex.xyz,1.0);
			OUT.hpos = mul(UNITY_MATRIX_MVP,pos);
			OUT.texcoord = IN.texcoord.xy * tile;
			//------------
			float3x3 tangentSpace = Level4_TangentSpace(IN.normal,IN.tangent);
			
			float3 vpos = mul(UNITY_MATRIX_MV,pos).xyz;
			OUT.eye = mul(tangentSpace,vpos);
			OUT.light = mul(tangentSpace,lightPos.xyz - vpos);
			
			return OUT;
		}

		//建立 射线.
		void setupRay(v2f IN,out float3 p,out float3 v){
			p = float3(IN.texcoord,0);
			v = normalize(IN.eye);
			v.z = abs(v.z);
			#ifdef DEPTH_BIAS
				float db = 1.0 - v.z; db *= db; db *= db; db = 1.0 - db * db;
				v.xy *= db;
			#endif
			v.xy *= depth;
		}
		
		float4 normalMapping(sampler2D colorMap,sampler2D normalMap,float2 texcoord,v2f IN){
			float4 color = tex2D(colorMap,texcoord);
			
			float4 normal = tex2D(normalMap,texcoord);
			normal.xy = 2 * normal.xy - 1; //[0,1] -> [-1,1]
			normal.y = -normal.y;
			normal.z = sqrt(1.0 - dot(normal.xy,normal.xy));
			
			float3 l = normalize(IN.light);
			float3 v = normalize(IN.eye);
			
			float diff = saturate(dot(l,normal.xyz)); //dot(L,N); ->[0,1]
			float spec = saturate(dot(normalize(l - v),normal.xyz)); //dot(H,N)
			//衰减 因子
			float att = 1.0 - max(0,l.z);
			att = 1.0- att * att;
			
			float alpha = 1.0;
			#ifdef BORDER_CLAMP
				if(texcoord.x < 0) alpha = 0;
				if(texcoord.y < 0) alpha = 0;
				if(texcoord.x > tile) alpha = 0;
				if(texcoord.y > tile) alpha = 0;
			#endif
			float4 finalColor;
			finalColor.xyz = ambientColor * color.xyz + 
				att * (color.xyz * diffuseColor * diff + specularColor * pow(spec,shine));
			finalColor.w = alpha;
			return finalColor;
		}
		
		void rayIntersectRelaxedCone(sampler2D relief_map,inout float3 p, inout float3 v){
			const int coneSteps = 15;
			const int binarySteps = 5;
			
			float3 p0 = p;
			v /= v.z;
			
			float dist = length(v.xy);
			// cone steps
			for(int i=0;i<coneSteps;i++){
				float4 tex = tex2D(relief_map,p.xy);
				float height = saturate(tex.w - p.z);
				float coneRatio = tex.z;
				p += v * (coneRatio * height / (dist + coneRatio));
			}
			v *= p.z * .5;
			p = p0 + v;
			//binary steps
			for(int i=0;i<binarySteps;i++){
				float4 tex = tex2D(relief_map,p.xy);
				v *= 0.5;
				if(p.z < tex.w)
					p += v;
				else
					p -= v;
			}
		}
		
		
		
		float4 frag(v2f IN):COLOR{
			float3 p,v;
			setupRay(IN,p,v);
			rayIntersectRelaxedCone(_reliefMap,p,v);
			
			return normalMapping(_colorMap,_reliefMap,p.xy,IN);
		}
		
	ENDCG
	
	SubShader {
		Pass{
			Cull back
			AlphaTest GEqual 16
			
			CGPROGRAM
				#pragma exclude_renderers gles
				#pragma target 3.0
				#pragma vertex vert
				#pragma fragment frag
			ENDCG
		}
	} 
	
}
